package com.zte.cl.parser;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.zte.cl.entity.Expr;
import com.zte.cl.entity.Field;
import com.zte.cl.entity.PageTemplate;
import com.zte.cl.entity.Replace;
import com.zte.cl.parser.enums.ExtractType;
import com.zte.cl.parser.enums.PageType;

/**
 * 初始化页面解析模板
 * 
 * @author Administrator
 * 
 */
public class PageTemplateUtil {

	private final static Logger log = Logger.getLogger(PageTemplateUtil.class);

	private static List<PageTemplate> pages;

	private static Map<String, PageTemplate> pageMap;

	public static String getKey(String url, String pageType) {
		return url + "_" + pageType;
	}

	public static PageTemplate findPageTemplate(String url, String pageType) {
		if (pages == null) {
			load();
		}
		if (pageMap != null && pageMap.containsKey(getKey(url, pageType))) {
			return pageMap.get(getKey(url, pageType));
		}
		return null;
	}

	public static PageTemplate findPageTemplateByUrlPrefix(String url, String pageType) {
		if (pages == null) {
			load();
		}
		for (PageTemplate page : pages) {
			if (url.startsWith(page.getUrl()) && page.getType().toString().equals(pageType)) {
				return page;
			}
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	public static List<PageTemplate> buildPagePageTemplate(File file) {
		List<PageTemplate> tempPages = new ArrayList<PageTemplate>();
		// 创建saxReader对象
		SAXReader reader = new SAXReader();
		try {
			// 通过read方法读取一个文件 转换成Document对象
			Document document = reader.read(file);
			// 获取根节点元素对象
			Element node = document.getRootElement();
			List<Element> pageList = node.elements("page");
			if (pageList != null) {
				for (Element pageEle : pageList) {
					PageTemplate page = new PageTemplate();
					page.setName(pageEle.attributeValue("name"));
					page.setUrl(pageEle.attributeValue("url"));
					page.setType(PageType.getEnumFromString(pageEle.attributeValue("type")));
					List<Element> exprEleList = pageEle.elements("expr");
					if (exprEleList != null) {
						List<Expr> exprList = new ArrayList<Expr>();
						for (Element exprEle : exprEleList) {
							Expr expr = new Expr();
							expr.setExtractType(ExtractType.getEnumFromString(exprEle.attributeValue("extractType")));
							expr.setExprValue(exprEle.getText());
							if (exprEle.attributeValue("group") != null) {
								expr.setGroup(Integer.valueOf(exprEle.attributeValue("group")));
							}
							exprList.add(expr);
						}
						if (exprList.size() > 0) {
							page.setExprs(exprList);
						}
					}

					List<Element> fieldList = pageEle.elements("field");
					if (fieldList != null) {
						List<Field> fields = new ArrayList<Field>();
						for (Element fieldEle : fieldList) {
							Field f = new Field();
							f.setName(fieldEle.attributeValue("name"));
							f.setRequired(fieldEle.attributeValue("required"));
							f.setDefaultValue(fieldEle.attributeValue("defaultValue"));
							if (fieldEle.attributeValue("dateformat") != null) {
								f.setDateformat(fieldEle.attributeValue("dateformat"));
							}
							List<Element> fieldExprEleList = fieldEle.elements("expr");
							List<Expr> flExprList = new ArrayList<Expr>();
							for (Element feExpr : fieldExprEleList) {
								Expr expr = new Expr();
								expr.setExtractType(ExtractType.getEnumFromString(feExpr.attributeValue("extractType")));
								expr.setExprValue(feExpr.getText());
								if (feExpr.attributeValue("group") != null) {
									expr.setGroup(Integer.valueOf(feExpr.attributeValue("group")));
								}
								flExprList.add(expr);
							}
							if (flExprList.size() > 0) {
								f.setExprs(flExprList);
							}
							List<Element> replaceEleList = fieldEle.elements("replace");
							List<Replace> replaceList = new ArrayList<Replace>();
							for (Element reEl : replaceEleList) {
								Replace replace = new Replace();
								replace.setValue(reEl.attributeValue("value"));
								replace.setRegex(reEl.getText());
								replaceList.add(replace);
							}
							if (replaceList.size() > 0) {
								f.setReplaces(replaceList);
							}
							fields.add(f);
						}
						page.setFields(fields);
					}
					tempPages.add(page);
				}
			}
		} catch (Exception e) {
			log.error("execute PageTemplateUtil.Load()," + file.getName(), e);
		}

		return tempPages;
	}

	public static List<File> readXmlFile(File file) {
		List<File> fileList = new ArrayList<File>();
		if (file.isDirectory()) {
			File[] files = file.listFiles();
			for (int i = 0; i < files.length; i++) {
				if (files[i].isDirectory()) {
					fileList.addAll(readXmlFile(files[i]));
				} else if (files[i].getName().endsWith(".xml")) {
					fileList.add(files[i]);
				}
			}
		} else {
			if (file.getName().endsWith(".xml")) {
				fileList.add(file);
			}
		}
		return fileList;
	}

	public static void load() {
		log.info("初始化模板...");
		List<PageTemplate> tempPages = new ArrayList<PageTemplate>();
		try {
			String templatePath = Thread.currentThread().getContextClassLoader().getResource("").getPath() + "template";
			templatePath = java.net.URLDecoder.decode(templatePath, "utf-8");
			File folder = new File(templatePath);
			if (folder.isDirectory()) {
				List<File> fileList = readXmlFile(folder);
				for (int i = 0; i < fileList.size(); i++) {
					tempPages.addAll(buildPagePageTemplate(fileList.get(i)));
				}

/*				File[] fileList = folder.listFiles();
				for (int i = 0; i < fileList.length; i++) {
					if (!fileList[i].getName().endsWith(".xml")) {
						continue;
					}
					tempPages.addAll(buildPagePageTemplate(fileList[i]));
				}*/

			}
		} catch (Exception e) {
			log.error("execute PageTemplateUtil.Load()", e);
		}finally{
			log.info("execute PageTemplateUtil.Load()");
		}
		pages = tempPages;
		if (pages != null) {
			pageMap = new HashMap<String, PageTemplate>();
			for (PageTemplate p : pages) {
				pageMap.put(getKey(p.getUrl(), p.getType().toString()), p);
			}
		}
	}

	public static synchronized void refresh() {
		load();
	}
}
